package com.gao.d_selector.f;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;

/**
 * @author gao
 * @time 2020/08/13 21:25:02
 */
public class Client {
    private Selector seletor;
    private SocketChannel channel;

    public Client(int port) throws IOException {
        seletor = Selector.open();
        channel = SocketChannel.open();
        channel.configureBlocking(false);
        channel.register(seletor, SelectionKey.OP_CONNECT);
        channel.connect(new InetSocketAddress("127.0.0.1", port));
    }

    public void start() {
        try {
            while (true) {
                int n = seletor.select();
                if (n > 0) {
                    Set<SelectionKey> selectedKeys = seletor.selectedKeys();
                    Iterator<SelectionKey> it = selectedKeys.iterator();
                    while (it.hasNext()) {
                        SelectionKey key = it.next();
                        it.remove();
                        if (key.isValid() && key.isConnectable()) {
                            connect(key);
                        }
                        if (key.isValid() && key.isWritable()) {
                            write(key);
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void write(SelectionKey key) {
        try {
            for (int i = 1; i <= 10; i++) {
                SocketChannel channel = (SocketChannel) key.channel();
                // msg'length is 65
                String msg = "Where there is a will,there is a way.It is never too old to learn";

                // 测试使用，让Client发送的消息有各种随机的长度，随机长度范围：65 ~ 365
                int n = new Random().nextInt(301) + 1;
                for (int j = 0; j < n; j++) {
                    msg += "!";
                }

                int msgLength = msg.length();
                byte[] headBytes = Utils.intToByte(msg.length());
                ByteBuffer buffer = ByteBuffer.allocate(msg.length() + 4);
                buffer.put(headBytes);
                buffer.put(msg.getBytes());
                // write mode to read mode
                buffer.flip();
                channel.write(buffer);
                System.out.println("client send: " + msgLength + "" + msg);
            }
            key.cancel();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void connect(SelectionKey key) {
        try {
            SocketChannel channel = (SocketChannel) key.channel();
            boolean b = channel.finishConnect();
            if (b) {
                channel.register(seletor, SelectionKey.OP_WRITE);
                System.out.println("connect to server...");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) throws IOException {
        Client client = new Client(8888);
        client.start();
    }
}
